package com.heima.wemedia.scan.service.impl;

import com.alibaba.fastjson.JSON;
import com.heima.feign.api.ArticleFeignClient;
import com.heima.green.AliyunGreenTemplate;
import com.heima.minio.MinIOTemplate;
import com.heima.model.article.dto.ArticleDto;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.wemedia.entity.WmChannel;
import com.heima.model.wemedia.entity.WmNews;
import com.heima.model.wemedia.entity.WmUser;
import com.heima.wemedia.scan.dao.WmChannelDao;
import com.heima.wemedia.scan.dao.WmNewsDao;
import com.heima.wemedia.scan.dao.WmUserDao;
import com.heima.wemedia.scan.service.WmNewsScanService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class WmNewsScanImpl implements WmNewsScanService {

    @Resource
    private WmNewsDao wmNewsDao;
    @Resource
    private AliyunGreenTemplate aliyunGreenTemplate;
    @Resource
    private MinIOTemplate minIOTemplate;
    @Resource
    private ArticleFeignClient articleFeignClient;
    @Resource
    private WmChannelDao wmChannelDao;
    @Resource
    private WmUserDao wmUserDao;

    @Override
    public void newsAutoScan(Long newsId) {
        //1.拿到文章内容和图片
        WmNews wmNews = wmNewsDao.queryById(newsId);
        //      "1"是待审核状态   状态不是1的话,就直接return,不再执行后续代码
        if (wmNews.getStatus() != 1) {
            return;
        }
        //2.有文本内容和图片数据
        Map<String, Object> textAndImage = getTextAndImage(wmNews);

        //3.文本审核 
        String text = textAndImage.get("text").toString();
        Boolean textResult = textScan(wmNews, text);
        if (!textResult) {
            return;
        }
        //4.图片审核
        //TODO 项目上线之前需要把图片审核方式修改为根据 URL审核
        List<String> imagesResult = (List<String>) textAndImage.get("images");
        Boolean imageResult = imageScan(wmNews, imagesResult);
        if (!textResult) {
            return;
        }

        //没有到发布时间,只修改状态即可,到了发布时间需要发送文章到app端
        if (wmNews.getPublishTime().getTime() > System.currentTimeMillis()) {
            //5.更新数据库文章状态
            extracted(wmNews, 8, "审核通过");
        } else {
            //6.发布文章--审核通过 且 发布时间<当前时间
            saveArticle(wmNews);
        }

    }

    /**
     * 通过feign调用发布文章到app端
     *
     * @param wmNews
     */
    private void saveArticle(WmNews wmNews) {
        //1. 创建对象, 封装请求参数
        ArticleDto articleDto = new ArticleDto();
        BeanUtils.copyProperties(wmNews, articleDto);
        //自己处理数据 newsId  channelName  layout  authorId  authorName
        articleDto.setNewsId(wmNews.getId());
        articleDto.setLayout(wmNews.getType());

        WmChannel wmChannel = wmChannelDao.queryById(wmNews.getChannelId());
        if (wmChannel != null) {
            articleDto.setChannelName(wmChannel.getName());
        }

        articleDto.setAuthorId(wmNews.getUserId());

        WmUser wmUser = wmUserDao.queryById(wmNews.getUserId());
        if (wmUser != null) {
            articleDto.setAuthorName(wmUser.getNickname());
        }

        //2. 调用文章服务发布文章
        ResponseResult responseResult = articleFeignClient.saveArticle(articleDto);
        if (responseResult.getCode() == 200) {
            //3. 修改文章状态为已发布
            updateStatus(wmNews, 9, "文章已发布");
        }
    }

    /**
     * 修改文章状态
     *
     * @param wmNews
     */
    private void updateStatus(WmNews wmNews, int status, String reason) {
        wmNews.setStatus(status);
        wmNews.setReason(reason);
        wmNewsDao.update(wmNews);
    }

    //图片审核方法
    private Boolean imageScan(WmNews wmNews, List<String> images) {
        //遍历图片数组,获取每个图片的url
        List<byte[]> collect = images.stream().map(url -> minIOTemplate.downLoadFile(url)).collect(Collectors.toList());
        //下载图片字节数据
        Map<String, String> stringStringMap = aliyunGreenTemplate.greenImageScan(collect);
        //审核通过
        if ("pass".equals(stringStringMap.get("suggestion"))) {
            return true;
        }
        //需要人工审核 状态改成3
        if ("review".equals(stringStringMap.get("suggestion"))) {
            extracted(wmNews, 3, "等待人工审核");
            return false;
        }
        //审核直接失败 状态改成2
        if ("block".equals(stringStringMap.get("suggestion"))) {
            extracted(wmNews, 2, "图片包含非法内容");
            return false;
        }
        return false;
    }

    //文本审核方法
    private boolean textScan(WmNews wmNews, String text) {
        Map<String, String> result = aliyunGreenTemplate.greenTextScan(text);

        //审核通过
        if ("pass".equals(result.get("suggestion"))) {
            return true;
        }
        //需要人工审核 状态改成3
        if ("review".equals(result.get("suggestion"))) {
            extracted(wmNews, 3, "等待人工审核");
            return false;
        }
        //审核直接失败 状态改成2
        if ("block".equals(result.get("suggestion"))) {
            extracted(wmNews, 2, "文章包含非法内容");
            return false;
        }
        return false;


    }

    //审核后修改数据库状态的方法
    private void extracted(WmNews wmNews, int status, String reason) {
        wmNews.setStatus(status);
        wmNews.setReason(reason);
        wmNewsDao.update(wmNews);
    }

    private Map<String, Object> getTextAndImage(WmNews wmNews) {
        StringBuilder sb = new StringBuilder();
        List<String> images = new ArrayList<>();

        //2.1 抽取文章文本内容 (标题,内容)
        //标题中的文本
        sb.append(wmNews.getTitle());

        List<Map> maps = JSON.parseArray(wmNews.getContent(), Map.class);

        for (Map map : maps) {
            //内容中的文本
            if ("text".equals(wmNews.getType())) {
                sb.append(map.get("value") + ";");
            }
            //内容图片添加到List集合
            if ("image".equals(wmNews.getType())) {
                images.add(map.get("value").toString());
            }
        }

        //2.2 抽取文章封面图片
        String newsImages = wmNews.getImages();
        //封面不为空
        if (StringUtils.isNoneEmpty(newsImages)) {
            String[] imageUrls = newsImages.split(",");
            images.addAll(Arrays.asList(imageUrls));
        }

        Map<String, Object> textAndImage = new HashMap<>();
        textAndImage.put("text", sb.toString());
        textAndImage.put("images", images);
        return textAndImage;
    }
}
